﻿using System;
using LightCAD.Three.OpenGL;

namespace LightCAD.Three
{

    public class WebGLCapabilities
    {
        public int maxAnisotropy = -1;
        public WebGLExtensions extensions;
        public string precision;
        public readonly string maxPrecision;
        public readonly bool isWebGL2 = true;//这个客户端和web不一样
        public readonly bool drawBuffers;
        public readonly bool logarithmicDepthBuffer;
        public readonly int maxTextures;
        public readonly int maxVertexTextures;
        public readonly int maxTextureSize;
        public readonly int maxCubemapSize;
        public readonly int maxAttributes;
        public readonly int maxVertexUniforms;
        public readonly int maxVaryings;
        public readonly int maxFragmentUniforms;
        public readonly bool vertexTextures;
        public readonly bool floatFragmentTextures;
        public readonly bool floatVertexTextures;
        public readonly int maxSamples;
        public static int Max_UniformBlock_Size { get; private set; } = 65536;

        public WebGLCapabilities(WebGLExtensions extensions, RenderParams parameters)
        {
            var maxUniformSize = gl.GetInteger(gl.MAX_UNIFORM_BLOCK_SIZE);
            if (maxUniformSize < 65536)
                Max_UniformBlock_Size = maxUniformSize;
            this.extensions = extensions;
            this.precision = parameters.precision != null ? parameters.precision : "highp";
            this.maxPrecision = getMaxPrecision(precision);
            if (maxPrecision != precision)
            {
                console.warn("THREE.WebGLRenderer:", precision, "not supported, using", maxPrecision, "instead.");
                precision = maxPrecision;
            }
            this.drawBuffers = isWebGL2 || extensions.has("WEBGL_draw_buffers");
            this.logarithmicDepthBuffer = parameters.logarithmicDepthBuffer;
            this.maxTextures = (int)gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
            this.maxVertexTextures = (int)gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
            this.maxTextureSize = (int)gl.getParameter(gl.MAX_TEXTURE_SIZE);
            this.maxCubemapSize = (int)gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
            this.maxAttributes = (int)gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
            this.maxVertexUniforms = (int)gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
            this.maxVaryings = (int)gl.getParameter(gl.MAX_VARYING_VECTORS);
            this.maxFragmentUniforms = (int)gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
            this.vertexTextures = maxVertexTextures > 0;
            this.floatFragmentTextures = isWebGL2 || extensions.has("OES_texture_float");
            this.floatVertexTextures = vertexTextures && floatFragmentTextures;
            this.maxSamples = isWebGL2 ? (int)gl.getParameter(gl.MAX_SAMPLES) : 0;

        }
        public int getMaxAnisotropy()
        {
            if (maxAnisotropy >= 0) return maxAnisotropy;

            if (extensions.has("EXT_texture_filter_anisotropic") || true)
            {
                var extension = extensions.get("EXT_texture_filter_anisotropic");
                maxAnisotropy = (int)gl.getParameter(gl.MAX_TEXTURE_MAX_ANISOTROPY);
            }
            else
            {
                maxAnisotropy = 0;
            }

            return maxAnisotropy;
        }
        public string getMaxPrecision(string precision)
        {
            if (precision == "highp")
            {
                if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 &&
                    gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0)
                {
                    return "highp";
                }
                precision = "mediump";
            }
            if (precision == "mediump")
            {
                if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 &&
                    gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0)
                {
                    return "mediump";
                }
            }
            return "lowp";
        }
    }
}
